#include <iostream>
using namespace std;

#define THREE

#if defined ONE

void Swap(int& x, int& y)
{
    int temp;

    temp = x;
    x    = y;
    y    = temp;

    return;
}

int main(void)
{
    int a = 100;
    int b = 200;

    cout << "交换前,a的值:" << a << endl;
    cout << "交换前,b的值:" << b << endl;

    Swap(a, b);

    cout << "交换后,a的值:" << a << endl;
    cout << "交换后,b的值:" << b << endl;

    return 0;
}

#elif defined TWO

double Values[] = { 10.1, 12.6, 33.1, 24.1, 50.0 };

double& SetValue(int i)
{
    double& Ref = Values[i];   // 引用在创建时，必须被初始化

    return Ref;   // Ref是一个引用变量,Ref 引用 Values[i]
}

int main(void)
{
    cout << "改变前的值" << endl;
    for (int i = 0; i < 5; i++)
    {
        cout << "Values[" << i << "]=";
        cout << Values[i] << endl;
    }
    /**
     *下面精彩的部分来了
     */
    SetValue(1) = 20.23;
    SetValue(3) = 70.8;

    cout << "改变后的值" << endl;
    for (int i = 0; i < 5; i++)
    {
        cout << "Values[" << i << "]=";
        cout << Values[i] << endl;
    }

    return 0;
}

#elif defined THREE

/**
 * 当返回一个引用时,要注意被引用的对象不能超出作用域。所以返回一个对局部变量的引用是不合法的，但是可以返回一个对静态变量的引用
 *
 * 局部变量放在栈里面(stack里面)  static型的变量放在全局存储区里面
 *   int& func()
 *   {
 *      int q;
 *      // return q;  在编译时发生错误
 *
 *      static int x;
 *      return x;    //安全，x在函数作用域外依然是有效的
 *   }
 */

int& GetStaticRef()
{
    static int num = 5;

    return num;
}

int main(void)
{
    int& Ref = GetStaticRef();

    cout << "初始值:" << Ref << endl;

    Ref = 10;

    cout << "修改后的值:" << Ref << endl;
    cout << "再次调用函数后的值:" << GetStaticRef() << endl;

    GetStaticRef() = 100; //这个写法很有意思

    cout << "修改后的值:" << Ref << endl;
    cout << "再次调用函数后的值:" << GetStaticRef() << endl;
}

#endif

/**
 *  C++引用
 *
 *  引用变量是一个别名，也就是说，它是某个已经存在变量的另一个名称
 *  一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量
 *  引用必须在定义时初始化，并且一旦绑定到一个变量后，就不能再绑定到其他变量了
 *
 *  int a=110;
 *  int &ref=a;   //ref 是a的引用   就是表示ref是 int 类型的引用
 *  ref是a的别名，对ref的操作会直接作用于a
 *
 *  ref =10;  等同于 a=10
 *
 *  C++ 里面引用和指针  区别如下
 *
 *  不存在空引用,引用必须连接到一块合法的内存
 *  一旦引用被初始化为一个对象，就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象
 *  引用必须在创建时被初始化。指针可以在任何时间被初始化
 *  引用的对象必须是一个变量，而指针必须是一个地址(可以将一个常量数字，直接强制转换为指针类型，然后赋值给指针变量)
 *
 *  切记引用是不占用内存的(底层还是通过指针实现，但编译器会直接将其优化为直接操作所引用的对象)
 *
 *  不能有引用的引用 但可以有指针的指针
 *
 *  不能直接创建引用数组（对应指针数组），但可以创建数组的引用，例如：int (&ref)[10] = arr;   那么ref[i] 就等同于 arr[i]
 *
 *  可以创建指针数组，也可以创建指向数组的指针，例如：int *ptrArr[10]; 表示指针数组 (就是数组里面的元素为 指针)
 *
 *
 *  C++中创建引用
 *
 *  重要，可以试想变量名称是变量附属在内存位置中的标签，那么可以把引用当成是变量附属在内存位置中的第二个标签。因此 变量名称 等同于 变量引用
 *
 *  int & r=i;
 *  double & s=d;
 *  在上面的声明中 &读作引用
 *  因此，第一个声明可以读作"r是一个初始化为i的整型引用" 第二个声明可以读作"s是一个初始化为d的double型引用"
 */
